
package com.huaweicloud.saaslanding.install.applicationservice.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huaweicloud.saaslanding.basic.enumeration.AppTypeEnum;
import com.huaweicloud.saaslanding.basic.enumeration.SecurityGroupBelongEnum;
import com.huaweicloud.saaslanding.basic.enumeration.SubnetBelongEnum;
import com.huaweicloud.saaslanding.dao.common.entity.app.MonoAppLicenseModule;
import com.huaweicloud.saaslanding.dao.common.entity.security.SecurityGroup;
import com.huaweicloud.saaslanding.dao.common.entity.security.Subnet;
import com.huaweicloud.saaslanding.dao.common.entity.security.VpcPeering;
import com.huaweicloud.saaslanding.dao.common.repository.app.AppTemplateBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.app.MonoAppLicenseModuleBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.security.SecurityGroupBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.security.SubnetBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.security.VpcPeeringBaseMapper;
import com.huaweicloud.saaslanding.huawei.vpc.api.VpcApi;
import com.huaweicloud.saaslanding.huawei.vpc.enumeration.RouteTypeEnum;
import com.huaweicloud.saaslanding.huawei.vpc.model.HeadersDto;
import com.huaweicloud.saaslanding.huawei.vpc.request.CreatePeeringRequest;
import com.huaweicloud.saaslanding.huawei.vpc.request.CreateSecurityGroupRequest;
import com.huaweicloud.saaslanding.huawei.vpc.request.Routes;
import com.huaweicloud.saaslanding.huawei.vpc.request.VpcInfo;
import com.huaweicloud.saaslanding.huawei.vpc.response.PeeringResponse;
import com.huaweicloud.saaslanding.huawei.vpc.response.SecurityGroupResponse;
import com.huaweicloud.saaslanding.install.applicationservice.VpcService;
import com.huaweicloud.saaslanding.install.properties.DatabaseConfig;
import com.huaweicloud.saaslanding.install.properties.Iam;
import com.huaweicloud.saaslanding.install.properties.Idaas;
import com.huaweicloud.saaslanding.install.properties.Vpc;
import com.huaweicloud.saaslanding.install.util.EcsApiUtil;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 功能描述
 *
 * @since 2022-12-15
 */
@Service
@Slf4j
public class VpcServiceImpl implements VpcService {
    @Value("${saaslanding-install.endpoint.iam}")
    private String iamEndPoint;

    @Value("${saaslanding-install.endpoint.vpc}")
    private String vpcEndPoint;

    @Resource
    private Iam iam;

    @Resource
    private Vpc vpc;

    @Resource
    private SecurityGroupBaseMapper securityGroupBaseMapper;

    @Resource
    private DatabaseConfig databaseConfig;

    @Resource
    private EcsApiUtil ecsApiUtil;

    @Resource
    private Idaas idaas;

    @Resource
    private AppTemplateBaseMapper appTemplateBaseMapper;

    @Resource
    private MonoAppLicenseModuleBaseMapper monoAppLicenseModuleBaseMapper;

    @Resource
    private VpcPeeringBaseMapper vpcPeeringBaseMapper;

    @Resource
    private SubnetBaseMapper subnetBaseMapper;

    private HeadersDto getHeadersDto() {
        HeadersDto headersDto = new HeadersDto();
        headersDto.setIamEndpoint(iamEndPoint);
        headersDto.setIamDomainName(iam.getIamDomain());
        headersDto.setIamUserName(iam.getIamUser());
        headersDto.setIamPassword(iam.getIamPassword());
        headersDto.setProjectId(iam.getProjectId());
        headersDto.setVpcEndpoint(vpcEndPoint);
        return headersDto;
    }

    @Override
    public Boolean initVpcPeering() {

        // 创建vpc peering
        createVpcPeering();

        // 单体应用（License）应用模板表ID
        Long appId = appTemplateBaseMapper.selectIdByNameAndType(idaas.getApplicationHttpsMonoLicense().getName(),
            AppTypeEnum.BUSINESS.getLabel());

        // 创建安全组
        List<MonoAppLicenseModule> monoAppLicenseModuleList =
            monoAppLicenseModuleBaseMapper.selectList(new QueryWrapper<MonoAppLicenseModule>().eq("app_id", appId));
        List<com.huaweicloud.saaslanding.huawei.ecs.model.SecurityGroup> securityGroupList = new ArrayList<>();
        for (MonoAppLicenseModule monoAppLicenseModule : monoAppLicenseModuleList) {
            SecurityGroup securityGroup = createSecurityGroup(getHeadersDto(), appId, monoAppLicenseModule.getId());
            securityGroupList.add(
                new com.huaweicloud.saaslanding.huawei.ecs.model.SecurityGroup(securityGroup.getSecurityGroupUuid()));
        }
        // 创建license服务端ECS服务器
        ecsApiUtil.createEcs(appId, "license-server", databaseConfig.getConnectionInfo().getDbName(),
            securityGroupList);
        return true;
    }

    /**
     * 创建vpc peering
     */
    public void createVpcPeering() {
        // 初始化license服务侧 vpc对等连接
        CreatePeeringRequest createPeeringRequest = new CreatePeeringRequest();
        createPeeringRequest.setName("vpc-peering-" + vpc.getClientVpcId());

        VpcInfo requestVpcInfo = new VpcInfo();
        requestVpcInfo.setVpcId(vpc.getClientVpcId());
        requestVpcInfo.setTenantId(iam.getProjectId());
        VpcInfo acceptVpcInfo = new VpcInfo();
        acceptVpcInfo.setVpcId(vpc.getServerVpcId());
        acceptVpcInfo.setTenantId(iam.getProjectId());

        createPeeringRequest.setRequestVpcInfo(requestVpcInfo);
        createPeeringRequest.setAcceptVpcInfo(acceptVpcInfo);

        // 创建license 模块服务器（ecs），下面安装两个nginx
        PeeringResponse peeringResponse = VpcApi.addPeering(getHeadersDto(), createPeeringRequest);

        // 初始化license服务侧 vpc建立对等连接后的路由表规则
        // license服务端路由数据
        Routes routesMain = new Routes();
        routesMain.setNexthop(peeringResponse.getId());
        routesMain.setType(RouteTypeEnum.PEERING.getType());
        routesMain.setVpcId(vpc.getServerVpcId());
        routesMain.setDestination(vpc.getClientVpcDestination());

        // license客户端路由数据
        Routes routesClient = new Routes();
        routesClient.setNexthop(peeringResponse.getId());
        routesClient.setType(RouteTypeEnum.PEERING.getType());
        routesClient.setVpcId(vpc.getClientVpcId());
        routesClient.setDestination(vpc.getServerVpcDestination());

        // 存储路由数据
        VpcPeering vpcPeering = new VpcPeering();
        vpcPeering.setVpcPeeringUuid(peeringResponse.getId());
        vpcPeering.setRequestVpcUuid(vpc.getClientVpcId());
        vpcPeering.setAcceptVpcUuid(vpc.getServerVpcId());
        vpcPeering.setRequestRouteUuid(VpcApi.addRoute(getHeadersDto(), routesClient).getId());
        vpcPeering.setAcceptRouteUuid(VpcApi.addRoute(getHeadersDto(), routesMain).getId());
        vpcPeeringBaseMapper.insert(vpcPeering);
    }

    /**
     * 创建安全组
     *
     * @param headersDto iam请求头信息
     * @param appId 应用id
     * @param moduleId 模块id
     * @return 安全组信息
     */
    public SecurityGroup createSecurityGroup(HeadersDto headersDto, Long appId, Long moduleId) {
        CreateSecurityGroupRequest createSecurityGroupRequest = new CreateSecurityGroupRequest();
        createSecurityGroupRequest.setEnterpriseProjectId(iam.getEnterpriseProjectId());
        createSecurityGroupRequest.setName("security-group-" + moduleId);
        SecurityGroupResponse securityGroupResponse = VpcApi.addSecurityGroup(headersDto, createSecurityGroupRequest);

        SecurityGroup securityGroup = new SecurityGroup();
        securityGroup.setSecurityGroupUuid(securityGroupResponse.getId())
            .setSecurityGroupName(createSecurityGroupRequest.getName())
            .setIsCreate(true)
            .setAppId(appId)
            .setModuleId(moduleId)
            .setBelongTo(SecurityGroupBelongEnum.SERVER.getBelongTo());

        securityGroupBaseMapper.insert(securityGroup);
        return securityGroup;
    }

    @Override
    public Boolean deleteVpcPeering() {
        // 格式化license服务侧 vpc对等连接
        VpcApi.deletePeering(getHeadersDto(), "");
        // 格式化license服务侧 vpc建立对等连接后的路由表规则
        VpcApi.deleteRoute(getHeadersDto(), "");

        // TODO 安全组、安全组规则、ip地址组的删除
        return true;
    }

    @Override
    public Boolean deleteSubnet() {
        List<Subnet> subnets = subnetBaseMapper.selectList(
            new QueryWrapper<Subnet>().eq("is_del", 0).eq("belong_to", SubnetBelongEnum.CLIENT.getBelongTo()));
        if (!CollectionUtils.isEmpty(subnets)) {
            for (Subnet subnet : subnets) {
                try {
                    VpcApi.deleteSubnet(getHeadersDto(), subnet.getSubnetUuid());
                } catch (Exception e) {
                    log.error("删除子网 {} 失败，{}", subnet.getSubnetUuid(), e);
                }
            }
        }
        return true;
    }

}
